iT邦幫忙

2023 iThome 鐵人賽

DAY 12
0

Component 測試

今天來綜合一下前面寫的測試吧,利用useFetchUsers()拿到的資料更新 component ,再判斷顯示是否正確。
我們稍微改寫一下 useFetchUsers() ,讓他多回傳 loading 這個 state。

import axios from 'axios';
import { useState, useEffect } from 'react';

interface User {
    id: string;
    username: string;
}

function useFetchUsers() {
    const [users, setUsers] = useState<User[]>([]);
    const [loading, setLoading] = useState<boolean>(true);

    const fetchUsers = async () => {
        try {
            const result = await axios.get<User[]>('https://jsonplaceholder.typicode.com/users');
            setUsers(result.data);
            setLoading(false);
        } catch (error) {
            console.log(error);
        }
    };

    useEffect(() => {
        fetchUsers();
    }, []);

    return {users, loading};
}

export default useFetchUsers;

那我們建立一個 component 去顯示拿到的資料

import useFetchUsers from "../../utils/hooks/useFetchUsers";

const UserList = () => {

  const { users, loading } = useFetchUsers();

  return (
    <>
      <h1>Users</h1>
      {
        loading ?
          <p>loading...</p> :
          <>
            {users.map((user: any) => (
              <p key={user.id}>{user.username}</p>
            ))}
          </>
      }
    </>
  );
}

export default UserList;

這個 component 需要測試的有

  • 還沒拿到資料時要顯示 loading
  • 拿到資料後更新 component 的內容
import UserList from ".";
import { render, screen } from "@testing-library/react";
import '@testing-library/jest-dom';
import axios from "axios";

describe("UserList", () => {

  it("拿到users data 前 render loading", async () => {
    render(<UserList />);
    expect(screen.getByText("loading...")).toBeInTheDocument();
  });

  it("拿到users data 後 render users", async () => {

    const mockAxios = jest.spyOn(axios, 'get');
    mockAxios.mockResolvedValueOnce({
        data: [
            { id: '1', username: 'Dylan' },
            { id: '2', username: 'Chloe' },
            { id: '3', username: 'John' },
        ],
    });
    render(<UserList />);
    
    expect(await screen.findByText("Dylan")).toBeInTheDocument();
  
  });
});

在一進入畫面時 api 尚未回覆資料,所以第一個 loading 的測試不用去等待,利用 getByText來看 loading 的文字是否存在。

測試有資料時,由於在 useFetchUsers() 中有使用到 axios.get ,為了不讓測試受到網路狀態的影響,我們這邊要去模擬 axios ,最後使用 Day11 中提到的 findBy 去找的我們模擬的資料,就完成這個 component 的測試了。

這邊提醒一下,如果是有用到 <li> 的話,那就不要去使用 ByText 我之前不知道這件事測到往生,<li> 的話可以使用 ByRole 跟 length 去判斷 listItem數量是否正確。


如果有什麼錯誤的地方,再請各位大神指正


上一篇
Day 11 - React Testing Library 元素選取
下一篇
Day 13 - Redux Toolkit 測試
系列文
React Clean Code And Unit Tests - 利用測試寫出人類看得懂的React程式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言